﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Silverlight.Testing;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using SilverTile.Xaml;
using SilverTile.Sprites;
using SilverTile.Viewports;
using System.Linq;

namespace SilverTileTests
{
    [TestClass]
    public class XamlSpawnPointTests
    {
        [TestMethod]
        public void SpawnPoint_Should_Have_SpawnRate_And_SpawnProbability_Properties()
        {

            var spawnPoint = new SpawnPoint();

            var spriteType = new SpriteAnimation();

            spawnPoint.SpriteType = spriteType;
            Assert.AreSame(spriteType, spawnPoint.SpriteType, "SpriteType was not set correctly");
            Assert.AreSame(spawnPoint.SpriteType, spawnPoint.GetValue(SpawnPoint.SpriteTypeProperty), "SpriteType and SpriteTypeProperty does not return the same value");

            int expectedSpawnRate = 10;
            spawnPoint.SpawnRate = expectedSpawnRate;
            Assert.AreEqual(expectedSpawnRate, spawnPoint.SpawnRate, "SpawnRate was not set correctly");
            Assert.AreEqual(spawnPoint.SpawnRate, spawnPoint.GetValue(SpawnPoint.SpawnRateProperty), "SpawnRate and SpawnRateProperty does not return the same value");

            int expectedSpawnProbability = 20;
            spawnPoint.SpawnProbability = expectedSpawnProbability;
            Assert.AreEqual(expectedSpawnProbability, spawnPoint.SpawnProbability, "SpawnProbability was not set correctly");
            Assert.AreEqual(spawnPoint.SpawnProbability, spawnPoint.GetValue(SpawnPoint.SpawnProbabilityProperty), "SpawnProbability and SpawnProbabilityProperty does not return the same value");

            Assert.IsFalse(spawnPoint.SpawnAtStartup, "Default for SpawnAtEnter is not False");
            spawnPoint.SpawnAtStartup = true;
            Assert.AreEqual(true, spawnPoint.SpawnAtStartup, "SpawnAtEnter was not set correctly");
            Assert.AreEqual(spawnPoint.SpawnAtStartup, spawnPoint.GetValue(SpawnPoint.SpawnAtStartupProperty), "SpawnAtEnter and SpawnAtEnterProperty does not return the same value");

        }

        [TestMethod]
        public void SpawnPoint_Should_Raise_Spawned_Event_With_Arguments_Of_The_Expected_Type()
        {

            var spriteType = new SpriteAnimation();
            var spawnPoint = new SpawnPoint { SpawnProbability = 100, SpawnRate = 1, SpriteType = spriteType, SpriteClassName = typeof(DummySprite).AssemblyQualifiedName };
            var tile = new SpriteTile { X = 0, Y = 0, SpawnPoint = spawnPoint };

            var gameArea = new GameAreaGrid { Rows = 1, Columns = 1 };
            gameArea.BackgroundSprites.Add(tile);

            var gameWorld = new SilverTileGameWorld();
            gameWorld.GameAreas.Add(gameArea);
            gameWorld.ActiveArea = gameArea;
            gameWorld.LoadSpawnPoints(gameArea);

            gameWorld.Viewport = new Viewport(10, 10);

            bool spawnedRaised = false;
            
            gameWorld.Spawned += (s, e) =>
            {
                spawnedRaised = true;
                Assert.AreSame(spawnPoint, e.SpawnPoint, "SpawnPoint of spawned event was not the expected");
            };

            gameWorld.Update(TimeSpan.FromSeconds(2));

            Assert.IsTrue(spawnedRaised, "Spawned event was not raised");           

        }

        [TestMethod]
        public void SpawnPoint_With_SpawnAtStartup_Should_Spawn_Immediately()
        {

            var spriteType = new SpriteAnimation();
            var spawnPoint = new SpawnPoint { SpawnProbability = 100, SpawnRate = 1, SpriteType = spriteType, SpriteClassName = typeof(DummySprite).AssemblyQualifiedName, SpawnAtStartup = true };
            var tile = new SpriteTile { X = 0, Y = 0, SpawnPoint = spawnPoint };

            var gameArea = new GameAreaGrid { Rows = 1, Columns = 1 };
            gameArea.BackgroundSprites.Add(tile);

            var gameWorld = new SilverTileGameWorld();

            bool spawnedRaised = false;
            gameWorld.Spawned += (s, e) =>
            {
                spawnedRaised = true;
                Assert.AreSame(spawnPoint, e.SpawnPoint, "SpawnPoint of spawned event was not the expected");
            };
            
            gameWorld.GameAreas.Add(gameArea);
            gameWorld.ActiveArea = gameArea;
            gameWorld.LoadSpawnPoints(gameArea);

            gameWorld.Viewport = new Viewport(10, 10);

            Assert.IsTrue(spawnedRaised, "Spawned event was not raised");           

        }

        public class DummySprite : AnimatedSprite
        {
            public DummySprite(int width, int height)
                : base(width, height)
            { }
        }

    }
}